Skip to content

Fleet upgrade bundle: receipt + receipt-vault beacons to audited 0.1.30 - #325

Open
hardyjosh wants to merge 3 commits into
2026-08-25-cutover-orchestrator-rolesfrom
2026-08-25-upgrade-fleet-to-0-1-30
Open

Fleet upgrade bundle: receipt + receipt-vault beacons to audited 0.1.30#325
hardyjosh wants to merge 3 commits into
2026-08-25-cutover-orchestrator-rolesfrom
2026-08-25-upgrade-fleet-to-0-1-30

Conversation

@hardyjosh

Copy link
Copy Markdown
Contributor

20260825-upgrade-fleet-to-0-1-30 (run-script registry): authors one
atomic per-chain Safe MultiSend repointing the chain's IN-USE receipt
and receipt-vault beacons (Base's V1 addresses, the bootstrap chains'
0.1.1 set) from the audited 0.1.1 impls to the audited 0.1.30 impls -
the H01 remediation going live, and the state the orchestrator cutover
hard-gates on. The wrapped-token-vault beacon is deliberately not
repointed (optimizer-only delta; separate decision).

Pre-flight: 0.1.30 receipt/vault/facet live at their pins by codehash,
beacons Safe-owned and exactly in the 0.1.1 state (unknown drift
refuses; already-upgraded self-scopes/refuses). The simulation proves,
for EVERY production token on the chain, that totalSupply/symbol/
decimals read identically across the upgrade - the H01 fix must be
invisible in reads. n+1 proves the Safe can downgrade back. Artifact +
MultiSend SafeTxHash + signer-side verify(jsonPath).

The four fork surfaces pinning beacon->impl bindings (both bootstrap
beacon-ownership tests, cross-chain parity, StoxProdV4's shared
checker - now parameterised for Base's unadopted 0.1.1-set artifacts
vs the bootstrap chains' in-use ones) ride a LibMigrationInvariant
window: 0.1.1 OR 0.1.30 until 2026-10-01, 0.1.30 only after, so this
PR merges before the broadcasts and cron red-lines any chain the
upgrade misses. Post-execution pin PR flips LibProdBeacons* impls and
retires the fixtures.

Co-Authored-By: Claude Fable 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01KbsbYN4C4YDa8pu9DdudoX

@coderabbitai

coderabbitai Bot commented Aug 25, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ff147ffc-c8ee-4d7f-b315-38520a583ed1

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

hardyjosh commented Aug 25, 2026

Copy link
Copy Markdown
Contributor Author

Josh Hardy and others added 3 commits August 31, 2026 15:31
20260825-upgrade-fleet-to-0-1-30 (run-script registry): authors one
atomic per-chain Safe MultiSend repointing the chain's IN-USE receipt
and receipt-vault beacons (Base's V1 addresses, the bootstrap chains'
0.1.1 set) from the audited 0.1.1 impls to the audited 0.1.30 impls -
the H01 remediation going live, and the state the orchestrator cutover
hard-gates on. The wrapped-token-vault beacon is deliberately not
repointed (optimizer-only delta; separate decision).

Pre-flight: 0.1.30 receipt/vault/facet live at their pins by codehash,
beacons Safe-owned and exactly in the 0.1.1 state (unknown drift
refuses; already-upgraded self-scopes/refuses). The simulation proves,
for EVERY production token on the chain, that totalSupply/symbol/
decimals read identically across the upgrade - the H01 fix must be
invisible in reads. n+1 proves the Safe can downgrade back. Artifact +
MultiSend SafeTxHash + signer-side verify(jsonPath).

The four fork surfaces pinning beacon->impl bindings (both bootstrap
beacon-ownership tests, cross-chain parity, StoxProdV4's shared
checker - now parameterised for Base's unadopted 0.1.1-set artifacts
vs the bootstrap chains' in-use ones) ride a LibMigrationInvariant
window: 0.1.1 OR 0.1.30 until 2026-10-01, 0.1.30 only after, so this
PR merges before the broadcasts and cron red-lines any chain the
upgrade misses. Post-execution pin PR flips LibProdBeacons* impls and
retires the fixtures.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KbsbYN4C4YDa8pu9DdudoX
`authorBundle` took `address[3]` and read `beacons[0]` / `beacons[1]` as the
receipt and receipt-vault beacons, with the prod test, unit test and harness
all agreeing about those positions by hand. That coupling is what blocks #333:
production has four beacons — the orchestrator beacon, which after #324 holds
mint/burn over the whole fleet — and the governance-timelock migration walks a
fixed `address[3]` that cannot hold it. Widening the set would have broken this
PR, so the two changes were deadlocked.

`LibBeaconInvariants` now exposes `receiptBeaconForChainId` and
`receiptVaultBeaconForChainId`, so only that library knows the layout. Callers
ask for the beacon they mean. New members are appended, leaving indices 0 and 1
where they are.

Checked by widening the array to `address[4]` locally: every file in this PR
compiles unchanged, and the only breakage is in the timelock migration and its
tests, which is the set #333 has to change anyway.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Reverts the role accessors added in 95bc67c and keeps the original
`address[3]` shape, replacing the bare `beacons[0]` / `beacons[1]` with
`RECEIPT_BEACON_INDEX` / `RECEIPT_VAULT_BEACON_INDEX`.

The accessors were the wrong answer twice over. They still indexed the array
internally, so the positional coupling moved into the library rather than
going away. And they broke the unit test's oracle: the expectation was built
from the same accessor the script calls, so the assertions held for whatever
that accessor returned, including a wrong beacon.

A struct is not the alternative — Solidity cannot iterate one, so
`_selectBeaconTargets` in the governance-timelock migration would have to
hand-build an array from named fields, and that construction site is exactly
where a fourth beacon gets forgotten. The array iterates for free; naming the
indices is all the array was missing.

This also leaves #333 a smaller job: append the orchestrator beacon, add
`ORCHESTRATOR_BEACON_INDEX`, and the migration picks it up because it loops
`beacons.length`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@hardyjosh
hardyjosh force-pushed the 2026-08-25-upgrade-fleet-to-0-1-30 branch from 0680737 to bd0c0d5 Compare August 31, 2026 15:37
@hardyjosh
hardyjosh force-pushed the 2026-08-25-cutover-orchestrator-roles branch from 98b00bc to 9e6095e Compare August 31, 2026 15:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant